home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / TCL1 / CEDITOR_ / CEDITORP.C1 < prev    next >
Text File  |  1990-06-10  |  10KB  |  340 lines

  1. /******************************************************************************
  2.  CEditorPane.c
  3.  
  4.                             The EditorPane Class
  5.  
  6.     Subclass of CEditText that implements a full text editor pane with undo
  7.     capabilities for the edit menu commands and for typing. This implementation
  8.     was inspired by an article in "The Essential Mac Tutor" by Melvyn D. Magree.
  9.     
  10.      Written by Johan A. Goossens
  11.      CompuServe: 74010,2576
  12.          
  13.     SUPERCLASS = CEditText.c
  14.  ******************************************************************************/
  15.  
  16. #include            <CBartender.h>
  17. #include            "CEditorPane.h"
  18.  
  19. extern CBartender    *gBartender;
  20. static long            cmdSelectAll;
  21. static Boolean        first = TRUE;
  22.  
  23. #define                delete        8
  24. #define                tab            9
  25. #define                retn        13
  26. #define                clear        27
  27. #define                cursLeft    28
  28. #define                cursRight    29
  29. #define                cursUp        30
  30. #define                cursDown    31
  31.  
  32.  
  33. /******************************************************************************
  34.  IEditorPanePane
  35.         Initialize an EditorPane object.
  36.         All parameters are standard, with the exception of firstTaskIndex.
  37.         This should give the index into the STR# 130 (STRtaskNames) resource
  38.         where the undo strings reside. Strings for cut,copy,paste,clear,type
  39.         and delete are required (and in that order). firstTaskIndex gives the
  40.         index for cut.
  41.  ******************************************************************************/
  42.  
  43. void CEditorPane::IEditorPane(CView *anEnclosure, CBureaucrat *aSupervisor,
  44.                         int aWidth, int aHeight,
  45.                         int aHEncl, int aVEncl,
  46.                         SizingOption aHSizing, SizingOption aVSizing,
  47.                         int aLineWidth, int theTaskIndex)
  48. {
  49.     short        itemNo;
  50.  
  51.     CEditText::IEditText(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl,
  52.                 aVEncl, aHSizing, aVSizing, aLineWidth);
  53.  
  54.     itsCurrentTask = NULL;
  55.     itsTaskIndex = theTaskIndex;
  56.     typing = 0;
  57.  
  58.     if (first)
  59.     {
  60.         itemNo = gBartender->FindItemText(MENUedit, (StringPtr) "\pSelect All");
  61.         if (itemNo)
  62.             cmdSelectAll = gBartender->FindCmdNumber(MENUedit, itemNo);
  63.         first = FALSE;
  64.     }
  65. }
  66.  
  67.  
  68. /******************************************************************************
  69.  UpdateMenus {OVERRIDE}
  70.         Perform menu management tasks.
  71.         Enable the "Select All" menu if one exists.
  72.  ******************************************************************************/
  73.  
  74. void    CEditorPane::UpdateMenus()
  75. {
  76.     inherited::UpdateMenus();
  77.     if (cmdSelectAll)
  78.         gBartender->EnableCmd(cmdSelectAll);
  79. }
  80.  
  81.  
  82. /******************************************************************************
  83.  DoCommand {OVERRIDE}
  84.          Perform the required commands. This method is a bit tricky. It is
  85.          called by the TCL. In this case a new task must be created to support
  86.          the undo capabilities. It is also called by the tasks to perform
  87.          all actions required for do, undo and redo. In this case no new task
  88.          should be created to avoid a perfect endless loop.
  89.          To support this logic, new command values are used for the various
  90.          edit commands. These new values are only used by the task manager,
  91.          so it becomes easy to determine whether the TCL called us or the
  92.          task called us.
  93.  ******************************************************************************/
  94.  
  95. void CEditorPane::DoCommand(long theCommand)
  96. {
  97.     typing = 0;
  98.  
  99.     if ((theCommand >= cmdCut) && (theCommand <= cmdClear))
  100.     {
  101.         itsCurrentTask = new(CEditorTask);
  102.         itsCurrentTask->IEditorTask(this, itsTaskIndex, cmdOffset + theCommand);
  103.         itsCurrentTask->Do();
  104.         itsSupervisor->Notify(itsCurrentTask);
  105.     }
  106.     else
  107.         if (theCommand == cmdSelectAll)
  108.             SelectAll();
  109.         else
  110.             if ((theCommand >= cmdMyCut) && (theCommand <= cmdMyClear))
  111.                 inherited::DoCommand(theCommand - cmdOffset);
  112.             else
  113.                 inherited::DoCommand(theCommand);
  114. }
  115.  
  116.  
  117. /******************************************************************************
  118.  DoClick {OVERRIDE}
  119.          Reset the typing indicator to make sure that a new task will be
  120.          created on the next keystroke.
  121.  ******************************************************************************/
  122.  
  123. void CEditorPane::DoClick(Point hitPt, short modifierKeys, long when)
  124. {
  125.     typing = 0;
  126.  
  127.     inherited::DoClick(hitPt, modifierKeys, when);
  128. }
  129.  
  130.  
  131. /******************************************************************************
  132.  DoKeyDown {OVERRIDE}
  133.          Handle keystrokes. A typing indicator is used to determine whether a
  134.          new typing task must be created. A sequence of keystrokes are collected
  135.          into one task. This indicator is reset by other commands and by the
  136.          undo mechanism. The value of the indicator specifies the number of
  137.          keystrokes in the current typing task.
  138.          The delete key is special. If this key is pressed when the typing
  139.          indicator is greater then zero, it is treated as part of the typing
  140.          task and all indicators and counters are adjusted. If the key is
  141.          pressed when the typing indicator is zero, it is treated as a seperate
  142.          command and a new task is created. If the delete key if pressed if the
  143.          current caret location is zero, we "beep" and ignore the command.
  144.  
  145.          The following keystrokes are supported at the moment:
  146.          
  147.          Cursor: left, right, up and down.
  148.              These key are not translated into tasks since they don't change
  149.              the text and and can't be undone. 
  150.          Clear:
  151.              This key is translated into the menu command "cmdClear".
  152.          Delete:
  153.              See above.
  154.          All ASCII values between 32 (space) and 127 (~):
  155.              These values are translated into a typing task. See discussion
  156.              above.
  157.          All other values:
  158.              In all other cases, we just "beep" and ignore the keystroke.
  159.  ******************************************************************************/
  160.  
  161. void CEditorPane::DoKeyDown(char theChar, Byte keyCode, EventRecord *macEvent)
  162. {
  163.     switch (theChar)
  164.     {
  165.         case cursLeft:
  166.         case cursRight:
  167.         case cursUp:
  168.         case cursDown:
  169.             inherited::DoKeyDown( theChar, keyCode, macEvent);
  170.             break;
  171.  
  172.         case clear:
  173.             DoCommand(cmdClear);
  174.             break;
  175.  
  176.         case delete:
  177.             if ((**macTE).selEnd == 0)
  178.             {
  179.                 SysBeep(1);
  180.                 return;
  181.             }
  182.  
  183.             if (typing)
  184.             {
  185.                 itsCurrentTask->Typing(-1);
  186.                 typing--;
  187.             }
  188.             else
  189.             {
  190.                 itsCurrentTask = new(CEditorTask);
  191.                 itsCurrentTask->IEditorTask(this, itsTaskIndex, cmdMyDelete);
  192.                 itsCurrentTask->Do();
  193.                 itsSupervisor->Notify(itsCurrentTask);
  194.             }
  195.             inherited::DoKeyDown(theChar, keyCode, macEvent);
  196.             break;
  197.  
  198.         default:
  199.             if ((theChar < 32 || theChar > 127)
  200.                     && theChar != tab && theChar != retn)
  201.             {
  202.                 SysBeep(1);
  203.                 return;
  204.             }
  205.  
  206.             if (typing)
  207.             {
  208.                 itsCurrentTask->Typing(+1);
  209.                 typing++;
  210.             }
  211.             else
  212.             {
  213.                 itsCurrentTask = new(CEditorTask);
  214.                 itsCurrentTask->IEditorTask(this, itsTaskIndex, cmdMyTyping);
  215.                 itsCurrentTask->Do();
  216.                 itsSupervisor->Notify(itsCurrentTask);
  217.                 typing = 1;
  218.             }
  219.  
  220.             inherited::DoKeyDown(theChar, keyCode, macEvent);
  221.             break;
  222.     }
  223. }
  224.  
  225.  
  226. /******************************************************************************
  227.  GetSize
  228.          Get the size of the TextEdit buffer.
  229.  ******************************************************************************/
  230.  
  231. void CEditorPane::GetSize(long *length, long *lines)
  232. {
  233.     *length = (**macTE).teLength;
  234.     *lines = (**macTE).nLines;
  235. }
  236.  
  237.  
  238. /******************************************************************************
  239.  GetSelection
  240.          Get the current selection parameters.
  241.  ******************************************************************************/
  242.  
  243. void CEditorPane::GetSelection(long *startSel, long *endSel)
  244. {
  245.     *startSel = (**macTE).selStart;
  246.     *endSel = (**macTE).selEnd;
  247. }
  248.  
  249.  
  250. /******************************************************************************
  251.  SetSelection
  252.          Set the current selection parameters.
  253.  ******************************************************************************/
  254.  
  255. void CEditorPane::SetSelection(long startSel, long endSel)
  256. {
  257.     Prepare();
  258.     TESetSelect(startSel, endSel, macTE);
  259. }
  260.  
  261.  
  262. /******************************************************************************
  263.  SelectAll
  264.          Set the current selection to the whole text.
  265.  ******************************************************************************/
  266.  
  267. void CEditorPane::SelectAll( void)
  268. {
  269.     SetSelection( 0, MAXINT);
  270. }
  271.  
  272.  
  273. /******************************************************************************
  274.  GetCharacter
  275.          Get the character at a certain position.
  276.  ******************************************************************************/
  277.  
  278. char CEditorPane::GetCharacter(long position)
  279. {
  280.     return *(*((**macTE).hText) + position);
  281. }
  282.  
  283.  
  284. /******************************************************************************
  285.  GetSelectionHandle
  286.          Copy the current selection into a handle. If no selection exists
  287.          the handle pointer is set to NULL and FALSE is returned to the caller.
  288.          Otherwise TRUE will be returned.
  289.  ******************************************************************************/
  290.  
  291. Boolean CEditorPane::GetSelectionHandle(Handle *data)
  292. {
  293.     long        startSel, endSel;
  294.  
  295.     GetSelection(&startSel, &endSel);
  296.     if (startSel == endSel)
  297.     {
  298.         data = NULL;
  299.         return(FALSE);
  300.     }
  301.     else
  302.     {
  303.         *data = NewHandle(endSel - startSel);
  304.         BlockMove(*((**macTE).hText) + startSel, **data, endSel - startSel);
  305.         return(TRUE);
  306.     }
  307. }
  308.  
  309. /******************************************************************************
  310.  SetSelectionHandle
  311.          Replace the current selection with the data in a handle.
  312.  ******************************************************************************/
  313.  
  314. void CEditorPane::SetSelectionHandle(Handle data)
  315. {
  316.     long        startSel, endSel;
  317.     long        size;
  318.  
  319.     Prepare();
  320.  
  321.     GetSelection(&startSel, &endSel);
  322.     TEDelete(macTE);
  323.  
  324.     size = GetHandleSize(data);
  325.     HLock(data);
  326.     TEInsert(*data, size, macTE);
  327.     HUnlock(data);
  328.     SetSelection(startSel, startSel + size);
  329. }
  330.  
  331.  
  332. /******************************************************************************
  333.  ResetTyping
  334.          Reset the typing indicator.
  335.  ******************************************************************************/
  336.  
  337. void CEditorPane::ResetTyping(void)
  338. {
  339.     typing = 0;
  340. }